import json
import time

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import logging
from urllib.parse import unquote, quote
import base64

from chat.RoomManager import *


logger = logging.getLogger('mylogger')


class ChatConsumer(WebsocketConsumer):
    # websocket建立连接时执行方法
    def __init__(self, *args, **kwargs):
        super().__init__(args, kwargs)
        self.userid = None
        self.userInfo = None
        self.room_group_name = None
        self.room_name = None

    def getUserInfo(self, cookie: str):
        data = unquote(cookie).lstrip('[').rstrip(']').split('; ')
        cookies = dict([item.split('=', 1) for item in data])
        self.userInfo = json.loads(cookies['userInfo'])

    def connect(self):
        # 从url里获取聊天室名字，为每个房间建立一个频道组
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        # 将房间名base64编码（支持非ascii字符），并用'-'和'.'取代'+''/'，同时去除末尾的'='
        self.room_group_name = 'room_%s' % base64.b64encode(self.room_name.encode('utf-8'), altchars=b'-.').decode('ascii').rstrip('=')
        for key, value in self.scope['headers']:
            if key == b'cookie':
                self.getUserInfo(value)
                break
        self.userid = self.scope['session']['_auth_user_id']
        # 将当前频道加入频道组
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )
        add_user(self.room_name, self.userInfo)
        # 接受所有websocket请求
        self.accept()
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {
                'type': 'user_list',
                'send': {
                    'type': 'user_list',
                    'list': get_room_users(self.room_name)
                }
            }
        )

    # websocket断开时执行方法
    def disconnect(self, close_code):
        # 从用户列表删除
        remove_user(self.room_name, self.userInfo)
        # 先从channel_group移除，再广播新的列表
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {
                'type': 'user_list',
                'send': {
                    'type': 'user_list',
                    'list': get_room_users(self.room_name)
                }
            }
        )

    def on_receive_message(self, message):
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {
                'sender_id': self.userid,  # 发送用户id
                'type': 'chat_message',
                'send': {  # 发送内容
                    'type': 'chat_msg',
                    'user': self.userInfo,
                    'time': int(time.time() * 1000),
                    'content': message
                }
            }
        )

    # 从websocket接收到消息时执行函数
    def receive(self, text_data):
        data = json.loads(text_data)
        if data['type'] == 'chat_msg':
            self.on_receive_message(data['payload'])

    # 从频道组接收到消息后执行方法
    def chat_message(self, event):
        # 过滤来自自己的消息
        if self.userid == event['sender_id']:
            event['send']['type'] = 'self'
        message = event['send']
        # 通过websocket发送消息到客户端
        self.send(text_data=json.dumps(message))

    # 发送用户列表
    def user_list(self, event):
        message = event['send']
        self.send(text_data=json.dumps(message))
